#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <pthread.h>
#include <thread>

void *start(void *args)
{
    // pid_t id = fork();
    // if(id == 0)
    // {
    //     //...
    // } 

    // pthread_detach(pthread_self()); // 自己把自己分离，主线程 pthread_join()失败，进程不会阻塞，直接return退出
    std::string name = static_cast<const char *>(args);
    while (true)
    {
        // std::cout << name << "local val a : " << (*addr)++ << std::endl;
        std::cout << "I am a new thread" << std::endl;
        sleep(1);
        // break;
    }
    // return 0;// 9. 新线程return，表示该线程退出
    // exit(1);// 任何地方调用exit,表示进程退出！
    pthread_exit((void*)10);
}

int main()
{
    pthread_t tid;
    // 创建进程
    pthread_create(&tid, nullptr, start, (void *)"thread-1");
    // pthread_detach(tid); // 把目标线程进行分离，pthread_join() 也是失败的，进程不会阻塞，直接return退出

    sleep(5);

    // pthread_cancel(tid);
    // std::cout << "取消线程：" << tid << std::endl;

    // sleep(5);

    // 进程等待
    void *ret = nullptr;
    int n = pthread_join(tid, &ret); // PTHREAD_CANCELED;
    std::cout << "new tjread exit code: " << (long long int)ret << ", n: " << n << std::endl;
    
    return 0;// 主线程return，表示进程结束！ 
}

// int *addr = nullptr;// 把线程内部的地址传出去，其他线程就可以看到

// void* start1(void *args)
// {
//     std::string name = static_cast<const char*>(args);
//     int a = 100;
//     addr = &a;
//     while (true)
//     {
//         std::cout << name << "local val a : " << a << std::endl;
//         sleep(1);
//     }
// }

// void* start2(void *args)
// {
//     std::string name = static_cast<const char*>(args);
//     while (true)
//     {
//         if(addr != nullptr)
//             std::cout << name << "local val a : " << (*addr)++ << std::endl;
//         sleep(1);
//     }
// }

// int main()
// {
//     pthread_t tid1, tid2;
//     // 创建进程
//     pthread_create(&tid1, nullptr, start1, (void*)"thread-1");
//     pthread_create(&tid2, nullptr, start2, (void*)"thread-2");

//     //进程等待
//     pthread_join(tid1, nullptr);
//     pthread_join(tid2, nullptr);
// }

// class ThreadData
// {
// public:
//     ThreadData()
//     {}

//     void Init(const std::string &name, int a, int b)
//     {
//         _name = name;
//         _a = a;
//         _b = b;
//     }

//     void Excute()
//     {
//         _result = _a + _b;
//     }

//     int Result(){ return _result; }

//     std::string Name(){ return _name; }

//     void SetID(pthread_t tid) { _tid = tid; }

//     pthread_t ID() { return _tid; }

//     int A() { return _a; }

//     int B() { return _b; }

//     ~ThreadData()
//     {}
// private:
//     std::string _name;
//     int _a;
//     int _b;
//     int _result;
//     pthread_t _tid;
// };

// // 5. 全局变量在线程内部是共享的
// int gval = 100; // 被所有线程共享【在全局数据区】

// std::string toHex(pthread_t tid)
// {
//     // 4. 进程内的函数，线程共享
//     char buffer[64];
//     snprintf(buffer, sizeof(buffer), "0x%lx", tid);
//     return buffer;
// }

// // 被重入了！
// void *routine1(void *args)
// {
//     // std::string name = static_cast<const char *>(args);
//     ThreadData *td = static_cast<ThreadData *>(args);
//     while (true)
//     {
//         // 3. 不加保护的情况下，显示器文件就是共享资源！
//         std::cout << "我是新线程，我的名字是：" << td->Name() << ", my tid is: " << toHex(pthread_self()) << ",全局变量(会修改)：" << gval << std::endl;
//         gval++;
//         td->Excute();
//         // std::cout << "task result is :" << td->Excute() << std::endl;
//         sleep(1);
//         break;
//     }
//     // return 0;
//     // 8. 返回值问题：返回参数，可以是变量、数字、对象！
//     // 8.1 理论上，堆空间也是共享的！谁拿着堆空间的入口地址，谁就能访问该堆区！
//     // return (void*)10;// 线程退出方式:1、线程入口函数retur    n，表示线程退出

//     return td;
// }

// #define NUM 10

// int main()
// {
//     ThreadData td[NUM];
//     // 准备我们要加工处理的数据
//     for(int i = 0; i < NUM; i++)
//     {
//         char id[64];
//         td[i].Init(id, i*10, i*20);
//     }

//     // 创建多线程
//     for(int i = 0; i < NUM; i++)
//     {
//         pthread_t id;
//         pthread_create(&id, nullptr, routine1, &td[i]);
//         td[i].SetID(id);
//     }

//     // 等待多线程
//     for(int i = 0; i < NUM; i++)
//     {
//         pthread_join(td[i].ID(), nullptr);
//     }

//     // 汇总处理结果
//     for(int i = 0; i <NUM; i++)
//     {
//         printf("td[%d]: %d+%d=%d[%ld]\n", i, td[i].A(), td[i].B(), td[i].Result(), td[i].ID());
//     }
// }

// // int main()
// // {
// //     // 1. 新线程和main线程谁先运行，不确定
// //     // 2. 线程创建出来，要对进程的时间片进行瓜分
// //     // 8. 传参问题：传递参数，可以是变量、数字、对象
// //     pthread_t tid1;
// //     ThreadData *td = new ThreadData("thread-1", 10, 20);// 主线程申请的堆空间
// //     pthread_create(&tid1, nullptr, routine1, td); // 创建线程

// //     // pthread_create(&tid1, nullptr, routine1, (void *)"thread-1"); // 创建线程

// //     // std::cout << "new thread tid：" << tid << std::endl;
// //     printf("new thread tid1: 0x%lx\n", tid1);

// //     // 7. 线程创建之后，也是要被等待和回收的！
// //     // 7.1 理由：a. 类似僵尸进程的问题
// //     //          b. 为了知道新线程的执行结果

// //     // void *ret = nullptr;// 线程所对应的返回值【线程routine1的返回值(void*)10】
// //     ThreadData *rtd = nullptr;
// //     int n = pthread_join(tid1, (void**)&rtd);// 我们可以保证，执行完毕，任务一定处理完了，结果变量一定已经被写入了！
// //     // int n = pthread_join(pthread_self(), nullptr); // 等待错误，等待的不是所产生的线程tid，而是自己本身的ID
// //     if (n != 0)
// //     {
// //         std::cout << "join error:" << n << "," << strerror(n) << std::endl;
// //         return 1;

// //     }
// //     std::cout << "join success!, ret: " << rtd->Result() << std::endl;
// //     delete td;
// //     // pthread_t tid2;
// //     // pthread_create(&tid2, nullptr, routine2, (void *)"thread-2");
// //     // printf("new thread tid2: 0x%lx\n", tid2);

// //     // pthread_t tid3;
// //     // pthread_create(&tid3, nullptr, routine, (void *)"thread-3");
// //     // printf("new thread tid: 0x%lx\n", tid3);

// //     // pthread_t tid4;
// //     // pthread_create(&tid4, nullptr, routine, (void *)"thread-4");
// //     // printf("new thread tid: 0x%lx\n", tid4);

// //     // while (true)
// //     // {
// //     //     std::cout << "我是main线程..." << std::endl;
// //     //     sleep(1);
// //     // }
// // }

// // // 5. 全局变量在线程内部是共享的
// // int gval = 100; // 被所有线程共享【在全局数据区】

// // std::string toHex(pthread_t tid)
// // {
// //     // 4. 进程内的函数，线程共享
// //     char buffer[64];
// //     snprintf(buffer, sizeof(buffer), "0x%lx", tid);
// //     return buffer;
// // }

// // void *routine1(void *args)
// // {
// //     std::string name = static_cast<const char *>(args);
// //     while (true)
// //     {
// //         // 3. 不加保护的情况下，显示器文件就是共享资源！
// //         std::cout << "我是新线程，我的名字是：" << name << ", my tid is: " << toHex(pthread_self()) << ",全局变量(会修改)：" << gval << std::endl;
// //         gval++;
// //         sleep(1);
// //         break;
// //     }
// //     return 0;
// // }

// // void *routine2(void *args)
// // {
// //     std::string name = static_cast<const char *>(args);
// //     while (true)
// //     {
// //         // 3. 不加保护的情况下，显示器文件就是共享资源！
// //         std::cout << "我是新线程，我的名字是：" << name << ", my tid is: " << toHex(pthread_self()) << ",全局变量（只检测）：" << gval << std::endl;
// //         sleep(1);
// //         // 6. 线程一旦出现问题，可能会导致其他线程其他线程全部崩溃
// //         // 6.1 异常的本质是信号
// //         int *p = nullptr; // 查页表失败 --> CPU内部的MMU报错 --> CPU触发软中断
// //         *p = 100;
// //     }
// //     return 0;
// // }

// // int main()
// // {
// //     // 1. 新线程和main线程谁先运行，不确定
// //     // 2. 线程创建出来，要对进程的时间片进行瓜分
// //     pthread_t tid1;

// //     pthread_create(&tid1, nullptr, routine1, (void *)"thread-1"); // 创建线程

// //     // std::cout << "new thread tid：" << tid << std::endl;
// //     printf("new thread tid1: 0x%lx\n", tid1);

// //     // 7. 线程创建之后，也是要被等待和回收的！
// //     // 7.1 理由：a. 类似僵尸进程的问题
// //     //          b. 为了知道新线程的执行结果
// //     // int n = pthread_join(tid1, nullptr);// 线程等待
// //     int n = pthread_join(pthread_self(), nullptr); // 等待错误，等待的不是所产生的线程tid，而是自己本身的ID
// //     if (n != 0)
// //     {
// //         std::cout << "join error:" << n << "," << strerror(n) << std::endl;
// //         return 1;
// //     }
// //     std::cout << "join success!" << std::endl;

// //     // pthread_t tid2;
// //     // pthread_create(&tid2, nullptr, routine2, (void *)"thread-2");
// //     // printf("new thread tid2: 0x%lx\n", tid2);

// //     // pthread_t tid3;
// //     // pthread_create(&tid3, nullptr, routine, (void *)"thread-3");
// //     // printf("new thread tid: 0x%lx\n", tid3);

// //     // pthread_t tid4;
// //     // pthread_create(&tid4, nullptr, routine, (void *)"thread-4");
// //     // printf("new thread tid: 0x%lx\n", tid4);

// //     // while (true)
// //     // {
// //     //     std::cout << "我是main线程..." << std::endl;
// //     //     sleep(1);
// //     // }
// // }